package preprocessing;

import weka.core.Attribute;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.converters.ConverterUtils;

public class Attribution_selection {

    public static int len,attribute,ranker=3;

    static int[] screening(Instances instances){ //按照不同属性进行分类
        int i,j,k,integer,counter,length,Y_class=instances.attributeStats(attribute).distinctCount;
        int []p=new int[Y_class];
        int []choice=new int[attribute-ranker];
        double [][]data=new double[len][attribute];
        double []H_Y=new double[attribute];
        double []H_YX=new double[attribute];

        p[0]=(instances.attributeStats(attribute)).nominalCounts[0];
        for(i=1;i<Y_class;i++){
            p[i]=p[i-1]+(instances.attributeStats(attribute)).nominalCounts[i];
        }

        for(i=0;i<attribute;i++){
            length=instances.attributeStats(i).distinctCount;
            double [][]p_x=new double[2+Y_class][length];
            for(counter=0,integer=0,j=0; j<len;j++){
                data[j][i]=instances.instance(j).value(i);
                for(k=0;k<integer;k++){
                    if(p_x[0][k]==data[j][i]){
                        p_x[1][k]+=1.0;
                        if(j>=p[counter]){
                            counter++;
                        }
                        p_x[counter+2][k]+=1.0;
                        break;
                    }
                }
                if(k==integer) {
                    p_x[0][integer] = data[j][i];
                    integer++;
                }
            }
            H_Y[i]=information_entropy(p,Y_class);
            H_YX[i]=information_entropy(p_x,length,Y_class);
        }
        choice=selection(H_YX,H_Y);
        return choice;
    }

    public static double information_entropy(int []p_x,int length){
        double H_Y=(Math.round(Math.pow(10,10)*Math.log10(p_x[0]/len)/Math.log10(2))/1.0/Math.pow(10,10));
        for(int i=1;i<length;i++){
            double p=(p_x[i]-p_x[i-1])/len;
            H_Y=H_Y+(Math.round(p*Math.pow(10,10)*Math.log10(p)/Math.log10(2))/1.0/Math.pow(10,10));
        }
        return Math.abs(H_Y);
    }

    public static double information_entropy(double [][]p_x,int length,int raw){
        double H_YX=0;
        for(int i=0;i<length;i++){
            for(int j=0;j<raw;j++){
                if(p_x[j+2][i]!=0) {
                    H_YX = H_YX + (p_x[1][i] / len) * Math.round(Math.pow(10, 10) * (Math.log10(p_x[j + 2][i] / p_x[1][i]) / Math.log10(2))) / 1.0 / Math.pow(10, 10);
                }
            }
        }
        return Math.abs(H_YX);
    }

    public static int[] selection(double []H_YX,double []H_Y){
        double []IG=new double[attribute];
        double change;
        int exchange;
        int []order=new int[attribute];
        int []ordered=new int[attribute-ranker];
        for(int i=0;i<attribute;i++){
            IG[i]=H_Y[i]-H_YX[i];
            order[i]=i;
        }
        for(int i=0;i<attribute-1;i++){
            for(int j=i+1;j<attribute;j++){
                if(IG[i]>IG[j]){
                    change=IG[i];
                    IG[i]=IG[j];
                    IG[j]=change;
                    exchange=order[i];
                    order[i]=order[j];
                    order[j]=exchange;
                }
            }
        }
        for(int i=0;i<attribute-ranker;i++){
            ordered[i]=order[i];
        }
        return ordered;
    }

    public static void printAttribute(Instances instances)
    {
        int numOfAttributes = instances.numAttributes();
        for(int i = 0; i < numOfAttributes ;++i)
        {
            Attribute attribute = instances.attribute(i);
            System.out.print(attribute.name() + " ");
        }
        System.out.println();
        //打印实例
        int numOfInstance = instances.numInstances();
        for(int i = 0; i < numOfInstance; ++i)
        {
            Instance instance = instances.instance(i);
            System.out.print(instance.toString() + " " + "\n");
        }
    }

    public static void main(String[] args) throws Exception {
        int []choice=new int[ranker];
        ConverterUtils.DataSource source = new ConverterUtils.DataSource("/home/tang/appdata/weka-3-8-4/data/iris.arff");
        Instances instances= source.getDataSet();
        len=instances.numInstances();
        attribute=instances.numAttributes()-1;
        choice=screening(instances);
        for(int i=0;i<attribute-ranker;i++) {
            instances.deleteAttributeAt(choice[i]);
        }
        printAttribute(instances);
    }
}
